﻿using Common.Framework.Core.Extension;
using Serilog;
using Serilog.Events;
using Serilog.Formatting.Compact;
using Serilog.Sinks.MSSqlServer;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Common.Framework.Core.Serilog
{
    /// <summary>
    /// 
    /// </summary>
    public static class SerilogExtension
    {
        public static void InitLog()
        {
            Log.Logger = new LoggerConfiguration().ReadFrom.Configuration(ConfigurationExtension.Configuration)
            .Enrich.FromLogContext()
            .WriteTo.Console() //输出到控制台上的日志为正常格式,方便查看
            //.MinimumLevel.Debug() // 所有Sink的最小记录级别
            .MinimumLevel.Information() // 所有Sink的最小记录级别

            #region 如果需要使用数据库记录操作日志,请打开该方法,并安装包Serilog.Sinks.MSSqlServer
        //    .InformationLogWriteToSqlServer()
            #endregion

            //.WriteTo.File(new CompactJsonFormatter(), path: Path.Combine("logs\\verbose", "log-verbose-.txt"), rollingInterval: RollingInterval.Day,restrictedToMinimumLevel:LogEventLevel.Verbose)
            //.WriteTo.File(new CompactJsonFormatter(), path: Path.Combine("logs\\debug", "log-debug-.txt"), rollingInterval: RollingInterval.Day, restrictedToMinimumLevel: LogEventLevel.Debug)
            .WriteTo.File(new CompactJsonFormatter(), path: Path.Combine("logs\\information", "log-information-.txt"), rollingInterval: RollingInterval.Day, restrictedToMinimumLevel: LogEventLevel.Information)
            .WriteTo.File(new CompactJsonFormatter(), path: Path.Combine("logs\\warning", "log-warning-.txt"), rollingInterval: RollingInterval.Day, restrictedToMinimumLevel: LogEventLevel.Warning)
            .WriteTo.File(new CompactJsonFormatter(), path: Path.Combine("logs\\error", "log-error-.txt"), rollingInterval: RollingInterval.Day, restrictedToMinimumLevel: LogEventLevel.Error)
            .WriteTo.File(new CompactJsonFormatter(), path: Path.Combine("logs\\fatal", "log-fatal-.txt"), rollingInterval: RollingInterval.Day, restrictedToMinimumLevel: LogEventLevel.Fatal)
            //直接将information写入elk
            //.WriteTo.Elasticsearch(new Serilog.Sinks.Elasticsearch.ElasticsearchSinkOptions(new Uri("http://127.0.0.1:9200"))
            //
            //    MinimumLogEventLevel = LogEventLevel.Information,
            //    IndexFormat = $"micro-notice-test-stash-{DateTime.Now:yyyy.MM.dd}"
            //})
            .CreateLogger();
        }

        ///// <summary>
        ///// 自定义information级别日志写入数据库
        ///// </summary>
        ///// <param name="loggerConfiguration"></param>
        ///// <returns></returns>
        //private static LoggerConfiguration InformationLogWriteToSqlServer(this LoggerConfiguration loggerConfiguration)
        //{
        //    var columnOpts = new ColumnOptions();
        //    columnOpts.AdditionalColumns = new Collection<SqlColumn>
        //    {
        //        new SqlColumn{  ColumnName = "Id",DataType = System.Data.SqlDbType.BigInt, NonClusteredIndex= true }, //id
        //        new SqlColumn{  ColumnName = "ObjType",DataType = System.Data.SqlDbType.VarChar, DataLength=50}, //对象类型,比如: Order,User ....
        //        new SqlColumn{  ColumnName = "LogObjTypeAlias",DataType = System.Data.SqlDbType.VarChar, DataLength=50}, //对象类型别名
        //        new SqlColumn{  ColumnName = "OperationType",DataType = System.Data.SqlDbType.Int, NonClusteredIndex= true }, //操作类型,比如: 1,新增;2:删除;3:改;4:查
        //        new SqlColumn{  ColumnName = "OperationName",DataType = System.Data.SqlDbType.VarChar}, //操作类型,比如: 1,新增;2:删除;3:改;4:查
        //        new SqlColumn{  ColumnName = "OperatorId",DataType = System.Data.SqlDbType.BigInt}, //操作人uid
        //        new SqlColumn{  ColumnName = "OperateIp",DataType = System.Data.SqlDbType.VarChar, DataLength = 50 }, //客户端IP
        //        new SqlColumn{  ColumnName = "ServerMark",DataType = System.Data.SqlDbType.VarChar, DataLength = 50 }, //服务端机器唯一标记  Environment.MachineName
        //        new SqlColumn{  ColumnName = "DeleteFlag",DataType = System.Data.SqlDbType.Int},
        //        new SqlColumn{  ColumnName = "CreateTime",DataType = System.Data.SqlDbType.DateTime, NonClusteredIndex= true },
        //        new SqlColumn{  ColumnName = "UpdateTime",DataType = System.Data.SqlDbType.DateTime},
        //    };
        //    columnOpts.Id.DataType = System.Data.SqlDbType.BigInt;
        //    columnOpts.Store.Remove(StandardColumn.Properties); //移除默认字段 Properties
        //    columnOpts.Store.Remove(StandardColumn.Id);//移除默认id字段
        //    columnOpts.Store.Remove(StandardColumn.TimeStamp);//移除默认TimeStamp字段
        //    columnOpts.Store.Remove(StandardColumn.MessageTemplate);
        //    columnOpts.Level.DataLength = 50;
        //    var config = loggerConfiguration
        //        .WriteTo.Logger(s =>
        //          s.Filter.ByIncludingOnly(FilterData).WriteTo.MSSqlServer(
        //              ConfigurationExtension.Configuration["ConnectionString:DefaultConnectionString"], //可单独配置为日志使用单独的数据库
        //              sinkOptions: new MSSqlServerSinkOptions
        //              {
        //                  TableName = "SystemLog" + DateTime.Now.Year.ToString() + "0101", //表名称//sqlsugar分表要求
        //                  AutoCreateSqlTable = true
        //              },
        //              columnOptions: columnOpts,
        //              restrictedToMinimumLevel: LogEventLevel.Information));
        //    return config;
        //}

        /// <summary>
        /// 往数据库中保存的数据为
        /// Information级别下的 包含 ObjType 的key的Properties
        /// 和Error所有信息,Fatal所有信息
        /// </summary>
        /// <param name="logEvent"></param>
        /// <returns></returns>
        private static bool FilterData(LogEvent logEvent)
        {
            return logEvent.Properties.ContainsKey("ObjType") || logEvent.Level == LogEventLevel.Error || logEvent.Level == LogEventLevel.Fatal;
        }

    }
}
